package com.changgou.seckill.task;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.pojo.SeckillStatus;
import entity.IdWorker;
import entity.SystemConstants;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 描述
 *
 * @author www.itheima.com
 * @version 1.0
 * @package com.changgou.seckill.task *
 * @since 1.0
 */
@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private Environment env;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //创建订单 异步处理 加入一个注解
    @Async
    public void createrOrder(){

        //从队列中获取排队信息
        SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps(SystemConstants.SEC_KILL_USER_QUEUE_KEY).rightPop();


        try {
            if(seckillStatus!=null){
                //从队列中获取一个商品
                Object sgood = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();
                if(sgood!=null){// 判断队列中是否有商品，没有则说明抢完了
                    ///清理当前用户的排队信息
                    clearQueue(seckillStatus);
                    return;
                }


                //时间区间
                String time = seckillStatus.getTime();
                //用户登录名
                String username="szitheima";
                //用户抢购商品
                Long id = seckillStatus.getGoodsId();
                //获取商品数据
                SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);
                //如果没有库存。则直接抛出异常
                if(goods == null  || goods.getStockCount()<=0){
                    throw new RuntimeException("已售磬");
                }
                //如果有库存， 则创建秒杀商品订单
                SeckillOrder seckillOrder = new SeckillOrder();
                seckillOrder.setId(idWorker.nextId());
                seckillOrder.setSeckillId(id);
                seckillOrder.setMoney(goods.getCostPrice());
                seckillOrder.setUserId(username);
                seckillOrder.setCreateTime(new Date());
                seckillOrder.setStatus("0");
                //将秒杀订单存入redis中
                redisTemplate.boundHashOps(SystemConstants.SEC_KILL_ORDER_KEY).put(username,seckillOrder);

                //商品库存-1
                Long seckillGoodsCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(id, -1);//商品数量递减
                //库存减少
                //goods.setStockCount(goods.getStockCount()-1);
                //此处控制数量 用redis控制，不要用goods本身，因为每次操作都是基于内存操作，并发情况下会导致数据不精准
                goods.setStockCount(seckillGoodsCount.intValue());//根据计数器统计


                //判断当前商品是否还有库存
                if(goods.getStockCount()<=0){
                    //并且将商品数据同步到MYSQL中
                    seckillGoodsMapper.updateByPrimaryKey(goods);
                    //如果没有库存，则清空Redis缓存中该商品
                    redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX+time).delete(id);
                }else {
                    //如果有库存，则直数据重置到redis中
                    redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX+time).put(id,goods);
                }
                //抢单成功，更新抢单状态,排队->等待支付
                seckillStatus.setStatus(2);
                seckillStatus.setOrderId(seckillOrder.getId());
                seckillStatus.setMoney(Float.valueOf(seckillOrder.getMoney()));
                redisTemplate.boundHashOps("UserQueueStatus").put(username,seckillStatus);
                //发送延时消息到MQ中
                sendTimerMessage(seckillStatus);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }


    public void clearQueue(SeckillStatus seckillStatus){
        //清理排队标示
        redisTemplate.boundHashOps("UserQueueCount").delete(seckillStatus.getUsername());

        //清理抢单标示
        redisTemplate.boundHashOps("UserQueueStatus").delete(seckillStatus.getUsername());
    }


    /***
     * 发送延时消息到RabbitMQ中
     * @param seckillStatus
     */
    public void sendTimerMessage(SeckillStatus seckillStatus){
        rabbitTemplate.convertAndSend(env.getProperty("mq.pay.queue.seckillordertimerdelay"), (Object) JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("10000");
                return message;
            }
        });
    }


}
